package study.itwill.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.log4j.Logger;

public class FileIO {

	// Logger 클래스의 인스턴스를 받아온다.
	static Logger logger = Logger.getLogger(FileIO.class);
	
	private static FileIO current = null;
	
	public static FileIO getInstance() {
		if (current == null) {
			current = new FileIO();
		}
		
		return current;
	}
	
	public static void freeInstance() {
		if (current != null) {
			current = null;
		}
	}

	public boolean write(String path, byte[] buffer) {
		
		logger.debug("=========== method start >> write");
		
		// 리턴할 결과값
		boolean result = false;

		// 주어진 경로에서 File 객체 생성
		File f1 = new File(path);
		// 부모의 경로 얻기
		String parent = f1.getParent();

		if (parent != null) {
			// 부모의 경로만으로 File 객체 생성
			File f2 = new File(parent);

			// 이 경로가 없다면 생성
			if (!f2.exists()) {
				f2.mkdirs();
			}
		}

		// 선언부와 할당부가 분리되어 블록이 나누어져 있을 때,
		// 객체 선언 후, 명시적으로 null을 할당한다.
		FileOutputStream fos = null;

		try {
			fos = new FileOutputStream(path);
			fos.write(buffer);
			logger.debug("파일 저장 성공 >> " + path);

			// 정상 처리시 결과값 true로 설정
			result = true;
		} catch (FileNotFoundException e) {
			// fos = new FileOutputStream(PATH); 에서 에러나는 경우
			logger.error("파일 생성 실패 >> " + e.getLocalizedMessage());

			logger.error(e.getLocalizedMessage());
			logger.error(e.getStackTrace());
		} catch (IOException e) {
			// fos.write(buffer); 에서 에러나는 경우
			logger.error("파일 저장 실패 >> " + e.getLocalizedMessage());

			logger.error(e.getLocalizedMessage());
			logger.error(e.getStackTrace());
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {

					logger.error(e.getLocalizedMessage());
					logger.error(e.getStackTrace());
				} // end try~catch
			} // end if
		} // end try~catch~finally
		
		logger.debug("=========== method end >> write");

		return result;
	}

	public byte[] read(String path) {
		
		logger.debug("=========== method start >> read");
		
		// 읽은 내용이 담겨질 스트림
		byte[] data = null;

		FileInputStream fis = null;

		try {
			fis = new FileInputStream(path);

			// 읽은 내용을 담기 위한 배열은 파일의 용량만큼 사이즈를 할당한다.
			// fis.available() --> 열고 있는 파일의 크기
			data = new byte[fis.available()];

			// 파일 읽기
			fis.read(data);

			logger.debug("파일 읽기 성공 >> " + path);

		} catch (FileNotFoundException e) {
			logger.error("파일 열기 실패 >> " + e.getLocalizedMessage());

			logger.error(e.getLocalizedMessage());
			logger.error(e.getStackTrace());
		} catch (IOException e) {
			logger.error("파일의 내용 읽기 실패 >> " + e.getLocalizedMessage());

			logger.error(e.getLocalizedMessage());
			logger.error(e.getStackTrace());
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {

					logger.error(e.getLocalizedMessage());
					logger.error(e.getStackTrace());
				}
			}
		}
		
		logger.debug("=========== method end >> read");

		return data;
	}

	public boolean write(String path, String content) {
		
		logger.debug("=========== method start >> write");
		
		byte[] buffer = content.getBytes();
		boolean result = this.write(path, buffer);
		
		logger.debug("=========== method end >> write");
		
		return result;
	}

	public String read(String path, String encoding) {
		
		logger.debug("=========== method start >> read");
		
		byte[] data = this.read(path);
		String content = null;
		try {
			content = new String(data, encoding);
			content = content.trim();
		} catch (UnsupportedEncodingException e) {

			logger.error(e.getLocalizedMessage());
			logger.error(e.getStackTrace());
		}

		logger.debug("=========== method end >> read");
		
		return content;
	}

}
